package com.kanshu.ksgb.fastread.doudou.common.net.retrofit;

import android.text.TextUtils;
import android.util.Log;

import com.kanshu.ksgb.fastread.doudou.common.business.errorlog.utils.ErrorLogUtil;
import com.kanshu.ksgb.fastread.doudou.common.business.manager.MMKVDefaultManager;
import com.kanshu.ksgb.fastread.doudou.common.net.bean.ErrorLogRequest;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.concurrent.TimeUnit;

import okhttp3.Connection;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.platform.Platform;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import okio.BufferedSource;

/**
 * Created by wcy on 18/3/14
 */
public class MyHttpLoggingInterceptor implements Interceptor {
    private static final Charset UTF8 = Charset.forName("UTF-8");
    private final MyHttpLoggingInterceptor.Logger logger;
    private volatile HttpLoggingInterceptor.Level level;

    public MyHttpLoggingInterceptor() {
        this(MyHttpLoggingInterceptor.Logger.DEFAULT);
    }

    public MyHttpLoggingInterceptor(MyHttpLoggingInterceptor.Logger logger) {
        this.level = HttpLoggingInterceptor.Level.NONE;
        this.logger = logger;
    }

    public MyHttpLoggingInterceptor setLevel(HttpLoggingInterceptor.Level level) {
        if(level == null) {
            throw new NullPointerException("level == null. Use Level.NONE instead.");
        } else {
            this.level = level;
            return this;
        }
    }

    public HttpLoggingInterceptor.Level getLevel() {
        return this.level;
    }

    public Response intercept(Chain chain) throws IOException {
        String params = "";
        String api_result = "";
        HttpLoggingInterceptor.Level level = this.level;
        Request request = chain.request();
        if(level == HttpLoggingInterceptor.Level.NONE) {
            return chain.proceed(request);
        } else {
            boolean logBody = level == HttpLoggingInterceptor.Level.BODY;
            boolean logHeaders = logBody || level == HttpLoggingInterceptor.Level.HEADERS;
            RequestBody requestBody = request.body();
            boolean hasRequestBody = requestBody != null;
            Connection connection = chain.connection();
            Protocol protocol = connection != null?connection.protocol():Protocol.HTTP_1_1;
            String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
            if(!logHeaders && hasRequestBody) {
                requestStartMessage = requestStartMessage + " (" + requestBody.contentLength() + "-byte body)";
            }
            this.logger.log(requestStartMessage);
            if(logHeaders) {
                if(hasRequestBody) {
                    if(requestBody.contentType() != null) {
                        this.logger.log("Content-Type: " + requestBody.contentType());
                    }

                    if(requestBody.contentLength() != -1L) {
                        this.logger.log("Content-Length: " + requestBody.contentLength());
                    }
                }

                Headers headers = request.headers();
                int i = 0;

                for(int count = headers.size(); i < count; ++i) {
                    String name = headers.name(i);
                    if(!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
                        this.logger.log(name + ": " + headers.value(i));
                    }
                }

                if(logBody && hasRequestBody) {
                    if(this.bodyEncoded(request.headers())) {
                        this.logger.log("--> END " + request.method() + " (encoded body omitted)");
                    } else {
                        Buffer buffer = new Buffer();
                        requestBody.writeTo(buffer);
                        Charset charset = UTF8;
                        MediaType contentType = requestBody.contentType();
                        if(contentType != null) {
                            charset = contentType.charset(UTF8);
                        }

                        this.logger.log("");
                        if(isPlaintext(buffer)) {
                            String s = buffer.readString(charset);
                            params = s;
                            this.logger.log(s);
                            this.logger.log("--> END " + request.method() + " (" + requestBody.contentLength() + "-byte body)");
                        } else {
                            this.logger.log("--> END " + request.method() + " (binary " + requestBody.contentLength() + "-byte body omitted)");
                        }
                    }
                } else {
                    String s = request.url().toString();
                    if (!TextUtils.isEmpty(s) && s.indexOf("?") > 0) {
                        params = s.substring(s.indexOf("?") + 1);
                    }
                    this.logger.log("--> END " + request.method());
                }
            }

            long startNs = System.nanoTime();

            Response response;
            try {
                response = chain.proceed(request);
            } catch (Exception var27) {
                Log.e("Exception", "<-- HTTP FAILED: " + var27);
                return errorResponse(request, protocol);
            } catch (OutOfMemoryError error) {
                Log.e("OutOfMemoryError", error.getMessage());
                return errorResponse(request, protocol);
            }
            long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
            ResponseBody responseBody = response.body();
            long contentLength = responseBody.contentLength();
            String bodySize = contentLength != -1L?contentLength + "-byte":"unknown-length";
            this.logger.log("<-- " + response.code() + ' ' + response.message() + ' ' + response.request().url() + " (" + tookMs + "ms" + (!logHeaders?", " + bodySize + " body":"") + ')');
            if(logHeaders) {
                Headers headers = response.headers();
                int i = 0;

                for(int count = headers.size(); i < count; ++i) {
                    this.logger.log(headers.name(i) + ": " + headers.value(i));
                }

                if(logBody && HttpHeaders.hasBody(response)) {
                    if(this.bodyEncoded(response.headers())) {
                        this.logger.log("<-- END HTTP (encoded body omitted)");
                    } else {
                        BufferedSource source = responseBody.source();
                        source.request(9223372036854775807L);
                        Buffer buffer = source.buffer();
                        Charset charset = UTF8;
                        MediaType contentType = responseBody.contentType();
                        if(contentType != null) {
                            try {
                                charset = contentType.charset(UTF8);
                            } catch (UnsupportedCharsetException var26) {
                                this.logger.log("");
                                this.logger.log("Couldn't decode the response body; charset is likely malformed.");
                                this.logger.log("<-- END HTTP");
                                return response;
                            }
                        }

                        if(!isPlaintext(buffer)) {
                            this.logger.log("");
                            this.logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
                            return response;
                        }

                        if(contentLength != 0L) {
                            this.logger.log("");
                            String s = buffer.clone().readString(charset);
                            api_result = s;
                            this.logger.log(s);
                        }

                        this.logger.log("<-- END HTTP (" + buffer.size() + "-byte body)");
                    }
                } else {
                    this.logger.log("<-- END HTTP");
                }
            }
            if(!response.isSuccessful()) {
                String s = response.request().url().toString();
                String s1 = "";
                try {
                    s1 = responseBody.source().buffer().readString(UTF8);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (s.contains("yd/exceptionlog/report") || TextUtils.isEmpty(s1)) {
                    return response;
                }
                ErrorLogRequest mErrorLogRequest = new ErrorLogRequest();
                if (request.method().equals("GET")) {
                    mErrorLogRequest.receive_way = ErrorLogRequest.TYPE_GET;
                } else if (request.method().equals("POST")) {
                    mErrorLogRequest.receive_way = ErrorLogRequest.TYPE_POST;
                }
                mErrorLogRequest.parameter = params;
                mErrorLogRequest.api_status = response.code();
                mErrorLogRequest.api_result = s1;
                mErrorLogRequest.api_url = response.request().url().toString();
                ErrorLogUtil.httpLogReportByOkHttp(mErrorLogRequest);
            } else {
                if (tookMs / 1000 >= MMKVDefaultManager.getInstance().getHttpTimeoutUpload()) {
                    ErrorLogRequest mErrorLogRequest = new ErrorLogRequest();
                    if (request.method().equals("GET")) {
                        mErrorLogRequest.receive_way = ErrorLogRequest.TYPE_GET;
                    } else if (request.method().equals("POST")) {
                        mErrorLogRequest.receive_way = ErrorLogRequest.TYPE_POST;
                    }
                    mErrorLogRequest.parameter = params;
                    mErrorLogRequest.api_status = response.code();
                    mErrorLogRequest.api_result = "该接口从请求到返回花费的时间超过" + MMKVDefaultManager.getInstance().getHttpTimeoutUpload() + "s";
                    mErrorLogRequest.api_url = response.request().url().toString();
                    ErrorLogUtil.httpLogReportByOkHttp(mErrorLogRequest);

                }
            }
            return response;
        }
    }

    private Response errorResponse(Request request, Protocol protocol){
        Response.Builder builder = new Response.Builder();
        builder.message("");
        builder.request(request);
        builder.protocol(protocol);
        builder.code(300);
        builder.body(new ResponseBody() {
            @Override
            public MediaType contentType() {
                return null;
            }

            @Override
            public long contentLength() {
                return 0;
            }

            @Override
            public BufferedSource source() {
                return null;
            }
        });
        return builder.build();
    }

    static boolean isPlaintext(Buffer buffer) {
        try {
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64L?buffer.size():64L;
            buffer.copyTo(prefix, 0L, byteCount);

            for(int i = 0; i < 16 && !prefix.exhausted(); ++i) {
                int codePoint = prefix.readUtf8CodePoint();
                if(Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false;
                }
            }

            return true;
        } catch (EOFException var6) {
            return false;
        }
    }

    private boolean bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }

    public interface Logger {
        MyHttpLoggingInterceptor.Logger DEFAULT = new MyHttpLoggingInterceptor.Logger() {
            public void log(String message) {
                Platform.get().log(4, message, (Throwable)null);
            }
        };

        void log(String var1);
    }

    public static enum Level {
        NONE,
        BASIC,
        HEADERS,
        BODY;

        private Level() {
        }
    }
}
